package ar.com.photo_admin.domain

import java.text.SimpleDateFormat
import java.util.Date;
import java.util.List;
import java.util.Set;

class User extends DomainObject {
	
	transient springSecurityService

	// User auth info:
	String facebookUid
	
	String username
	
	String name
	
	String lastname
	
	String email
	
	String password
		
	boolean enabled = true
	
	boolean accountExpired = false
	
	boolean accountLocked = false
	
	boolean passwordExpired = false
	
	// Extra info:
	String telephone

	String address

	Date birthday
	
	String presentationText
	
	byte[] profileImage
	
	String profileImageType
	
	Boolean useFacebookProfileImage = false
	
	NotificationsConfiguration notificationsConfiguration

	// Transients fields
	String confirmPassword
	
	String oldPassword
	
	String captchaCode
	
	Set userAlbumAccesses
	
	Set userNotifications 
	
	static hasMany = [userAlbumAccesses : UserAlbumAccess, presentationPhotos : PresentationPhoto, events : Event, userNotifications : UserNotification, receivedMessages : UserMessage, sentMessages : Message]
		
	User() {
		notificationsConfiguration = new NotificationsConfiguration()
		notificationsConfiguration.user = this
	}

	static constraints = {
		username(blank:false, nullable:false, unique:true, matches: '[a-z0-9_.]+', size: 4..16)
		password(blank:true, nullable:true)
		
		password validator: { password, obj ->
			return obj.confirmPassword == null || obj.confirmPassword == password
		}

		name(blank:false, nullable:false, matches: '[a-zA-Záéíóú]+')
		lastname(blank:false, nullable:false, matches: '[a-zA-Záéíóú]+')
		email(email: true, blank:false, nullable:false, unique:true)
		telephone(nullable:true, matches: '[0-9-]+')
		address(nullable:true)
		birthday(nullable:true, max: new Date())
		facebookUid(nullable:true, unique:true)
		presentationText(nullable:true, size: 0..250)
		profileImage(nullable:true, maxSize: 32768 /* 32K */)
		profileImageType(nullable:true)
	}

	static transients = ["confirmPassword", "captchaCode", "oldPassword"]
	
	static mapping = {
		password column: "password"		
		tablePerHierarchy false
		table '`user`'
	}
	
	Set<Role> getAuthorities() {
		UserRole.findAllByUser(this).collect { it.role } as Set
	}
	
	Set<String> getRoles() {
		UserRole.findAllByUser(this).collect { it.role.authority } as Set
	}
	
	def hasRole(String role) {
		getRoles().contains(role)
	}

	def hasPhotographerRole() {
		getRoles().contains(Role.PHOTOGRAPHER_ROLE)
	}
		
	def hasClientRole() {
		getRoles().contains(Role.CLIENT_ROLE)
	}
	
	def hasAdminRole() {
		getRoles().contains(Role.ROLE_ADMIN)
	}
	
	def isOwner(Event event) {
		event.photographer == this || event.client == this || this.hasRole(Role.ROLE_ADMIN)
	}
	
	def isOwner(EventAlbum album) {
		isOwner(album.event)
	}
	
	def isOwner(EventPhoto photo) {
		photo.user == this || (photo.event != null && this.isOwner(photo.event))
	}
	
	def isAllowed(EventAlbum album) {
		def event = album.event
		isOwner(event) || this.getAlbumsWhereCanAccess().contains(album)
	}
	
	def isAllowed(EventPhoto photo) {
		photo.albums.find { this.isAllowed(it) } != null
	}
	
	def beforeInsert() {
		encodePassword()
	}

	def beforeUpdate() {
		if (isDirty('password')) {
			encodePassword()
		}
	}

	protected void encodePassword() {
		password = password ? springSecurityService.encodePassword(password) : "" 
			
		if (confirmPassword)
			confirmPassword = springSecurityService.encodePassword(confirmPassword)
	}
	
	public String toString() {
		return name + " " + lastname	
	}
	
	public def addClientRole() {
		if(!this.hasClientRole()) {
			def clientRole = Role.findByAuthority(Role.CLIENT_ROLE)
			UserRole.create(this, clientRole, true)		
		}
	}
	
	Set getAlbumsWhereCanAccess() {
		userAlbumAccesses.collect{ it.album }
	}
	
	Set getActiveAlbumsWhereCanAccess() {
		getAlbumsWhereCanAccess().findAll { !it.deleted }
	}
	
	def getActiveAlbumsWhereCanAccessIds() {
		getActiveAlbumsWhereCanAccess().collect { it.id }
	}
	
	User addToUserAlbumAccesses(EventAlbum album) {
		UserAlbumAccess.link(this, album)
		return this
	}
	
	User removeFromUserAlbumAccesses(EventAlbum album) {
		UserAlbumAccess.unlink(this, album)
		return this
	}
	
	Set getAllUserNotifications() {
		return userNotifications.collect { it.notification }
	}
	
	List getReceivedRawMessages() {
		return receivedMessages.collect { it.message }
	}
	
	User addToUserNotifications(Notification notification) {
		UserNotification.link(this, notification)
		return this
	}
	
	User removeFromUserNotifications(Notification notification) {
		UserNotification.unlink(this, notification)
		return this
	}
	
	boolean hasUnreadNotifications() {
		return userNotifications.any { !it.notified }
	}
	
	def getFormattedBirthday() {
		if (birthday)
			birthday.format('dd/MM/yyyy')
	}
}
